﻿using ReactiveUI.Fody.Helpers;
using ReactiveUI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using Newtonsoft.Json;
using System.Text.Json;
using System.ComponentModel;
using DynamicData.Kernel;

namespace WPF_DataGridFromJson_Demo.Models
{
    /// <summary>
    /// 分离面参数
    /// </summary>
    public class RotorSeparatePara : ReactiveObject, IDataErrorInfo
    {
        public int ID { get; set; }
        public int ParentID { get; set; }

        [Reactive]
        public bool IsSelected { get; set; }
        [Reactive]
        public double RotorSeparateX { get; set; }
        [Reactive]
        public string RotorSeparateName { get; set; }

        private bool _isBisection = true;
        public bool IsBisection
        {
            get => _isBisection;
            set
            {
                this.RaiseAndSetIfChanged(ref _isBisection, value);
                // 如果分段数验证通过，则重置偏移角度
                if (string.IsNullOrEmpty(ValidateProperty(nameof(RotorSegmentsNum))))
                {
                    RotorSeparateOffSetAngle = 0;
                }
                UpdateSegmentParameters(_rotorSegmentsNum, _isBisection, _rotorSeparateOffSetAngle);
                RaisePropertyChanged(nameof(Error)); // 确保错误信息被更新
            }
        }

        private int _rotorSegmentsNum = 1;
        public int RotorSegmentsNum
        {
            get => _rotorSegmentsNum;
            set
            {
                this.RaiseAndSetIfChanged(ref _rotorSegmentsNum, value);
                if (string.IsNullOrEmpty(ValidateProperty(nameof(RotorSegmentsNum))))
                {
                    RotorSeparateOffSetAngle = 0;
                }
                UpdateSegmentParameters(_rotorSegmentsNum, _isBisection, _rotorSeparateOffSetAngle);
                RaisePropertyChanged(nameof(Error)); // 确保错误信息被更新
            }
        }

        private double _rotorSeparateOffSetAngle = 0.0;
        public double RotorSeparateOffSetAngle
        {
            get => _rotorSeparateOffSetAngle;
            set
            {
                this.RaiseAndSetIfChanged(ref _rotorSeparateOffSetAngle, value);
                UpdateSegmentParameters(_rotorSegmentsNum, _isBisection, _rotorSeparateOffSetAngle);
                RaisePropertyChanged(nameof(Error)); // 确保错误信息被更新
            }
        }

        public string Error => ValidateAllProperties();

        public string this[string columnName]
        {
            get => ValidateProperty(columnName);
        }

        private string ValidateProperty(string propertyName)
        {
            string result = null;
            if (propertyName == nameof(RotorSegmentsNum))
            {
                if (RotorSegmentsNum < 1 || RotorSegmentsNum > 24)
                {
                    result = "分段数在1-24之间。";
                }
            }
            else if (propertyName == nameof(RotorSeparateOffSetAngle))
            {
                if (RotorSegmentsNum == 0)
                {
                    result = "分段数不能为零。";
                }
                else if (RotorSeparateOffSetAngle >= 360.0 / RotorSegmentsNum)
                {
                    result = $"偏移角度需小于 {360.0 / RotorSegmentsNum}°";
                }
            }
            return result;
        }

        private string ValidateAllProperties()
        {
            var errors = new List<string>
        {
            ValidateProperty(nameof(RotorSegmentsNum)),
            ValidateProperty(nameof(RotorSeparateOffSetAngle))
        };
            return string.Join(Environment.NewLine, errors.Where(error => !string.IsNullOrEmpty(error)));
        }

        #pragma warning disable CS0108 // 成员隐藏继承的成员；缺少关键字 new
        public event PropertyChangedEventHandler PropertyChanged;
        #pragma warning restore CS0108 // 成员隐藏继承的成员；缺少关键字 new

        protected virtual void RaisePropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public string SegmentParametersJson
        {
            get => System.Text.Json.JsonSerializer.Serialize(SegmentParameters, new JsonSerializerOptions { WriteIndented = true });
            set => SegmentParameters = System.Text.Json.JsonSerializer.Deserialize<ObservableCollection<RotorSegmentParameter>>(value);
        }

        private ObservableCollection<RotorSegmentParameter> _segmentParameters;

        public ObservableCollection<RotorSegmentParameter> SegmentParameters
        {
            get => _segmentParameters;
            set
            {
                this.RaiseAndSetIfChanged(ref _segmentParameters, value);
            }
        }

        public RotorSeparatePara()
        {
            SegmentParameters = new ObservableCollection<RotorSegmentParameter>();
            SegmentParameters.Add(new RotorSegmentParameter(1, 0, 0));
        }

        public RotorSeparatePara(double rotorSeparateX, string rotorSeparateName, bool isBisection, int rotorSegmentsNum, string segmentParametersJson)
        {
            RotorSeparateX = rotorSeparateX;
            RotorSeparateName = rotorSeparateName;
            IsBisection = isBisection;
            RotorSegmentsNum = rotorSegmentsNum;
            SegmentParameters = new ObservableCollection<RotorSegmentParameter>();
            SegmentParametersJson = segmentParametersJson;
            if (segmentParametersJson == null)
            {
                InitializeSegmentParameters(rotorSegmentsNum, isBisection);
            }
        }

        private void InitializeSegmentParameters(int segmentsNum, bool isBisection)
        {
            double angle = isBisection ? 360 / segmentsNum : 0;
            for (int i = 0; i < segmentsNum; i++)
            {
                SegmentParameters.Add(new RotorSegmentParameter(i + 1, angle * i, 0));
            }
        }

        private void UpdateSegmentParameters(int segmentsNum, bool isBisection, double rotorSeparateOffSetAngle)
        {
            if (string.IsNullOrEmpty(Error))
            {
                if (SegmentParameters == null)
                {
                    SegmentParameters = new ObservableCollection<RotorSegmentParameter>();
                }

                double offSetAngle = isBisection ? rotorSeparateOffSetAngle : 0;
                double angle = isBisection ? 360.0 / segmentsNum : 0.0;

                for (int i = 0; i < segmentsNum; i++)
                {
                    if (i < SegmentParameters.Count)
                    {
                        SegmentParameters[i].SegmentID = i + 1;
                        SegmentParameters[i].SegmentAngle = angle * i + offSetAngle;
                    }
                    else
                    {
                        SegmentParameters.Add(new RotorSegmentParameter(i + 1, angle * i + offSetAngle, 0));
                    }
                }

                while (SegmentParameters.Count > segmentsNum)
                {
                    SegmentParameters.RemoveAt(SegmentParameters.Count - 1);
                }

                RaisePropertyChanged(nameof(SegmentParameters));
            }
        }
    }

    /// <summary>
    /// 分段参数
    /// </summary>
    public class RotorSegmentParameter : ReactiveObject
    {
        [Reactive]
        public int SegmentID { get; set; }
        [Reactive]
        public double SegmentAngle { get; set; }
        [Reactive]
        public double SegmentWeight { get; set; }

        public RotorSegmentParameter(int segmentID, double segmentAngle, double segmentWeight)
        {
            SegmentID = segmentID;
            SegmentAngle = segmentAngle;
            SegmentWeight = segmentWeight;
        }

        public RotorSegmentParameter() { }
    }
}
